Skip to content

Conversation

@kpreid
Copy link
Contributor

@kpreid kpreid commented Nov 4, 2025

[Original description:] This seems to help LLVM notice that dropping the elements in the destructor of IntoIter is not necessary. In cases it doesn’t help, it should be cheap since it is just one assignment.

This PR adds a function to vec::IntoIter() which is used used by fold() and spec_extend(), when those operations complete, to forget the zero remaining elements and only deallocate the allocation, ensuring that there will never be a useless loop to drop zero remaining elements when the iterator is dropped.

This is my first ever attempt at this kind of codegen micro-optimization in the standard library, so please let me know what should go into the PR or what sort of additional systematic testing might indicate this is a good or bad idea.

…()`.

This seems to help LLVM notice that dropping the elements in the
destructor is not necessary.
@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-libs Relevant to the library team, which will review and decide on the PR/issue. labels Nov 4, 2025
@rustbot
Copy link
Collaborator

rustbot commented Nov 4, 2025

r? @Mark-Simulacrum

rustbot has assigned @Mark-Simulacrum.
They will have a look at your PR within the next two weeks and either review your PR or reassign to another reviewer.

Use r? to explicitly pick a reviewer

@Kobzol
Copy link
Member

Kobzol commented Nov 4, 2025

@bors try @rust-timer queue

@rust-timer

This comment has been minimized.

@rust-bors

This comment has been minimized.

rust-bors bot added a commit that referenced this pull request Nov 4, 2025
Explicitly forget the zero remaining elements in `vec::IntoIter::fold()`.
@rustbot rustbot added the S-waiting-on-perf Status: Waiting on a perf run to be completed. label Nov 4, 2025
@rust-bors
Copy link

rust-bors bot commented Nov 4, 2025

☀️ Try build successful (CI)
Build commit: ae97583 (ae975837374d0ef9f9abcb691803628d975e8fb2, parent: e5efc336720901420a8891dcdb67ca0a475dc03c)

@rust-timer

This comment has been minimized.

#[no_mangle]
pub fn vec_into_iter_drop_option(v: vec::Vec<(usize, Option<Bomb>)>) -> usize {
// CHECK-NOT: panic
// CHECK-NOT: Bomb$u20$as$u20$core..ops..drop..Drop
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion: CHECK-NOT tests are generally quite fragile, being prone to accidentally checking for something that never existed at all, or having the implementation in the standard library change such that a previously-useful test no longer does anything useful.

Thus I would suggest that whatever you're checking for here you also write another function that intentionally does trigger whatever you expect to not be there in this one, with positive CHECKs for the same things that are CHECK-NOTs here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. However, I encounter a problem: I add more tests to this file and LLVM decides that they should call drop_in_place::<IntoIter>() instead of inlining it, defeating the entire point of this change. That’s a sign that this optimization is fragile and more work is needed, I guess. (Or maybe the perf results will show that it’s good despite that.)

I am now trying to write more explicit code that doesn’t rely on inlining to help.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I’ve pushed a new commit 5fa286d that performs explicit forgetting instead of relying on inlining and dead code elimination to achieve anything.

// There are in fact no remaining elements to forget, but by doing this we can avoid
// potentially generating a needless loop to drop the elements that cannot exist at
// this point.
self.forget_remaining_elements();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍, makes sense to me. It being a consuming method also means that any writes into self that this does should optimize out comparatively easily. (Assuming, at least, that we get dead_on_return on the self parameter properly.)

This has the same end goal as the previous commit but does not rely on
compiler optimizations to delete the unwanted code; instead it enters a
code path which explicitly frees the allocation and forgets the
`IntoIter`.
@rust-timer
Copy link
Collaborator

Finished benchmarking commit (ae97583): comparison URL.

Overall result: ❌✅ regressions and improvements - no action needed

Benchmarking this pull request means it may be perf-sensitive – we'll automatically label it not fit for rolling up. You can override this, but we strongly advise not to, due to possible changes in compiler perf.

@bors rollup=never
@rustbot label: -S-waiting-on-perf -perf-regression

Instruction count

Our most reliable metric. Used to determine the overall result above. However, even this metric can be noisy.

mean range count
Regressions ❌
(primary)
- - 0
Regressions ❌
(secondary)
0.6% [0.5%, 0.6%] 3
Improvements ✅
(primary)
- - 0
Improvements ✅
(secondary)
-0.2% [-0.2%, -0.2%] 2
All ❌✅ (primary) - - 0

Max RSS (memory usage)

Results (primary 3.3%)

A less reliable metric. May be of interest, but not used to determine the overall result above.

mean range count
Regressions ❌
(primary)
3.3% [3.3%, 3.3%] 1
Regressions ❌
(secondary)
- - 0
Improvements ✅
(primary)
- - 0
Improvements ✅
(secondary)
- - 0
All ❌✅ (primary) 3.3% [3.3%, 3.3%] 1

Cycles

Results (secondary -2.7%)

A less reliable metric. May be of interest, but not used to determine the overall result above.

mean range count
Regressions ❌
(primary)
- - 0
Regressions ❌
(secondary)
- - 0
Improvements ✅
(primary)
- - 0
Improvements ✅
(secondary)
-2.7% [-2.7%, -2.7%] 1
All ❌✅ (primary) - - 0

Binary size

Results (primary 0.0%, secondary 0.1%)

A less reliable metric. May be of interest, but not used to determine the overall result above.

mean range count
Regressions ❌
(primary)
0.0% [0.0%, 0.1%] 5
Regressions ❌
(secondary)
0.1% [0.1%, 0.1%] 1
Improvements ✅
(primary)
-0.1% [-0.1%, -0.1%] 1
Improvements ✅
(secondary)
- - 0
All ❌✅ (primary) 0.0% [-0.1%, 0.1%] 6

Bootstrap: 473.413s -> 473.632s (0.05%)
Artifact size: 390.72 MiB -> 390.71 MiB (-0.00%)

@rustbot rustbot removed the S-waiting-on-perf Status: Waiting on a perf run to be completed. label Nov 5, 2025
@lqd
Copy link
Member

lqd commented Nov 5, 2025

@bors try @rust-timer queue

@rust-timer
Copy link
Collaborator

Awaiting bors try build completion.

@rustbot label: +S-waiting-on-perf

@rust-bors

This comment has been minimized.

rust-bors bot added a commit that referenced this pull request Nov 5, 2025
Explicitly forget the zero remaining elements in `vec::IntoIter::fold()`.
@rustbot rustbot added the S-waiting-on-perf Status: Waiting on a perf run to be completed. label Nov 5, 2025
@rust-bors
Copy link

rust-bors bot commented Nov 5, 2025

☀️ Try build successful (CI)
Build commit: 48bf163 (48bf1634d442e6680a26e6e6305239e51914dbb3, parent: 53efb3d4f3b67d189a0c72eb475a52017d79d609)

@rust-timer
Copy link
Collaborator

Queued 48bf163 with parent 53efb3d, future comparison URL.
There are currently 2 preceding artifacts in the queue.
It will probably take at least ~3.9 hours until the benchmark run finishes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

S-waiting-on-perf Status: Waiting on a perf run to be completed. S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-libs Relevant to the library team, which will review and decide on the PR/issue.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants